/*     */ package com.zimbra.cs.servlet;
/*     */ 
/*     */ import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.Builder;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.RemoteIP;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Config;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.util.Zimbra;
/*     */ import java.io.IOException;
/*     */ import java.util.Map;
/*     */ import java.util.Set;
/*     */ import java.util.Timer;
/*     */ import java.util.TimerTask;
/*     */ import java.util.concurrent.atomic.AtomicInteger;
/*     */ import javax.servlet.FilterChain;
/*     */ import javax.servlet.FilterConfig;
/*     */ import javax.servlet.ServletException;
/*     */ import javax.servlet.ServletRequest;
/*     */ import javax.servlet.ServletResponse;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ import javax.servlet.http.HttpServletResponse;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class ZimbraInvalidLoginFilter
/*     */   extends DoSFilter
/*     */ {
/*     */   private static final int DEFAULT_MAX_FAILED_LOGIN = 5;
/*     */   private int maxFailedLogin;
/*     */   private Map<String, AtomicInteger> numberOfFailedOccurence;
/*     */   private Map<String, Long> suspiciousIpAddrLastAttempt;
/*     */   private final int DEFAULT_DELAY_IN_MIN_BETWEEN_REQ_BEFORE_REINSTATING = 60;
/*     */   private int delayInMinBetwnReqBeforeReinstating;
/*     */   private final int DEFAULT_REINSTATE_IP_TASK_INTERVAL_IN_MIN = 5;
/*     */   private int reinstateIpTaskIntervalInMin;
/*     */   private static final int MIN_TO_MS = 60000;
/*     */   public static final String AUTH_FAILED = "auth.failed";
/*     */   public int maxSizeOfFailedIpDb;
/*     */   public int DEFAULT_SIZE_OF_FAILED_IP_DB;
/*     */   
/*     */   public ZimbraInvalidLoginFilter()
/*     */   {
/*  49 */     this.DEFAULT_DELAY_IN_MIN_BETWEEN_REQ_BEFORE_REINSTATING = 60;
/*     */     
/*  51 */     this.DEFAULT_REINSTATE_IP_TASK_INTERVAL_IN_MIN = 5;
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*  56 */     this.DEFAULT_SIZE_OF_FAILED_IP_DB = 7000;
/*     */   }
/*     */   
/*     */ 
/*     */   public void init(FilterConfig filterConfig)
/*     */     throws ServletException
/*     */   {
/*  63 */     super.init(filterConfig);
/*  64 */     Provisioning prov = Provisioning.getInstance();
/*     */     try {
/*  66 */       this.maxFailedLogin = prov.getConfig().getInvalidLoginFilterMaxFailedLogin();
/*     */     } catch (ServiceException e) {
/*  68 */       this.maxFailedLogin = 5;
/*     */     }
/*     */     try
/*     */     {
/*  72 */       this.reinstateIpTaskIntervalInMin = prov.getConfig().getInvalidLoginFilterReinstateIpTaskIntervalInMin();
/*     */     }
/*     */     catch (ServiceException e) {
/*  75 */       this.reinstateIpTaskIntervalInMin = 5;
/*     */     }
/*     */     try
/*     */     {
/*  79 */       this.delayInMinBetwnReqBeforeReinstating = prov.getConfig().getInvalidLoginFilterDelayInMinBetwnReqBeforeReinstating();
/*     */     }
/*     */     catch (ServiceException e) {
/*  82 */       this.delayInMinBetwnReqBeforeReinstating = 60;
/*     */     }
/*     */     try
/*     */     {
/*  86 */       this.maxSizeOfFailedIpDb = prov.getConfig().getInvalidLoginFilterMaxSizeOfFailedIpDb();
/*     */     } catch (ServiceException e) {
/*  88 */       this.maxSizeOfFailedIpDb = this.DEFAULT_SIZE_OF_FAILED_IP_DB;
/*     */     }
/*     */     
/*  91 */     this.numberOfFailedOccurence = new ConcurrentLinkedHashMap.Builder().maximumWeightedCapacity(this.maxSizeOfFailedIpDb).build();
/*     */     
/*     */ 
/*     */ 
/*  95 */     this.suspiciousIpAddrLastAttempt = new ConcurrentLinkedHashMap.Builder().maximumWeightedCapacity(this.maxSizeOfFailedIpDb).build();
/*     */     
/*     */ 
/*     */ 
/*  99 */     Zimbra.sTimer.schedule(new ReInStateIpTask(), 1000L, this.reinstateIpTaskIntervalInMin * 60000);
/*     */     
/* 101 */     ZimbraLog.misc.info("ZimbraInvalidLoginFilter initialized");
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
/*     */     throws IOException, ServletException
/*     */   {
/* 110 */     HttpServletRequest req = (HttpServletRequest)request;
/* 111 */     HttpServletResponse res = (HttpServletResponse)response;
/* 112 */     RemoteIP remoteIp = new RemoteIP(req, ZimbraServlet.getTrustedIPs());
/* 113 */     String clientIp = remoteIp.getOrigIP();
/* 114 */     if ((clientIp == null) || (getWhitelist().contains(clientIp)))
/*     */     {
/*     */ 
/* 117 */       chain.doFilter(request, response);
/* 118 */       return;
/*     */     }
/*     */     
/* 121 */     if (this.maxFailedLogin <= 0)
/*     */     {
/* 123 */       chain.doFilter(request, response);
/* 124 */       return;
/*     */     }
/* 126 */     if (this.suspiciousIpAddrLastAttempt.containsKey(clientIp)) {
/* 127 */       ZimbraLog.misc.info("Access to IP " + clientIp + "suspended, for repeated failed login.");
/* 128 */       res.sendError(503);
/* 129 */       return;
/*     */     }
/* 131 */     chain.doFilter(request, response);
/*     */     
/* 133 */     if (req.getAttribute("auth.failed") != null) {
/* 134 */       ZimbraLog.misc.info("Invalid login filter, checking if this was an auth req and authentication failed.");
/*     */       
/* 136 */       String clientIP = (String)req.getAttribute("request.ip");
/* 137 */       boolean loginFailed = ((Boolean)req.getAttribute("auth.failed")).booleanValue();
/* 138 */       if (loginFailed)
/*     */       {
/* 140 */         AtomicInteger count = null;
/* 141 */         if (this.numberOfFailedOccurence.containsKey(clientIp)) {
/* 142 */           count = (AtomicInteger)this.numberOfFailedOccurence.get(clientIp);
/*     */         } else {
/* 144 */           this.numberOfFailedOccurence.put(clientIp, new AtomicInteger(0));
/* 145 */           count = (AtomicInteger)this.numberOfFailedOccurence.get(clientIp);
/*     */         }
/*     */         
/* 148 */         if (count.incrementAndGet() > this.maxFailedLogin) {
/* 149 */           this.numberOfFailedOccurence.put(clientIp, count);
/* 150 */           this.suspiciousIpAddrLastAttempt.put(clientIp, Long.valueOf(System.currentTimeMillis()));
/*     */         }
/*     */         
/* 153 */         this.numberOfFailedOccurence.put(clientIp, count);
/*     */       }
/* 155 */       if (ZimbraLog.misc.isDebugEnabled()) {
/* 156 */         ZimbraLog.misc.debug("Login failed " + clientIP + ", " + loginFailed);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public void destroy()
/*     */   {
/* 169 */     super.destroy();
/* 170 */     this.numberOfFailedOccurence.clear();
/* 171 */     this.suspiciousIpAddrLastAttempt.clear();
/* 172 */     ZimbraLog.misc.info("ZimbraInvalidLoginFilter destroyed");
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public final class ReInStateIpTask
/*     */     extends TimerTask
/*     */   {
/*     */     public ReInStateIpTask() {}
/*     */     
/*     */ 
/*     */ 
/*     */     public void run()
/*     */     {
/* 186 */       Set<String> clientIps = ZimbraInvalidLoginFilter.this.suspiciousIpAddrLastAttempt.keySet();
/* 187 */       long now = System.currentTimeMillis();
/* 188 */       for (String clientIp : clientIps) {
/* 189 */         long lastLoginAttempt = ((Long)ZimbraInvalidLoginFilter.this.suspiciousIpAddrLastAttempt.get(clientIp)).longValue();
/* 190 */         if (now - lastLoginAttempt > ZimbraInvalidLoginFilter.this.delayInMinBetwnReqBeforeReinstating * 60000) {
/* 191 */           ZimbraInvalidLoginFilter.this.suspiciousIpAddrLastAttempt.remove(clientIp);
/* 192 */           ZimbraInvalidLoginFilter.this.numberOfFailedOccurence.remove(clientIp);
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/servlet/ZimbraInvalidLoginFilter.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */